package qiniu.voidcepc.voicepc.demos.web.server.impl;

import com.alibaba.dashscope.aigc.generation.Generation;
import com.alibaba.dashscope.aigc.generation.GenerationParam;
import com.alibaba.dashscope.aigc.generation.GenerationResult;
import com.alibaba.dashscope.common.Message;
import com.alibaba.dashscope.common.Role;
import com.alibaba.dashscope.exception.InputRequiredException;
import com.alibaba.dashscope.tools.FunctionDefinition;


import java.util.Arrays;

import com.alibaba.dashscope.exception.NoApiKeyException;
import com.alibaba.dashscope.tools.ToolCallBase;
import com.alibaba.dashscope.tools.ToolCallFunction;
import com.fasterxml.jackson.core.JsonProcessingException;
import com.fasterxml.jackson.databind.JsonMappingException;
import com.fasterxml.jackson.databind.ObjectMapper;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Service;
import org.springframework.web.multipart.MultipartFile;
import qiniu.voidcepc.voicepc.demos.web.aliyunllm.GetGenerationParam;
import qiniu.voidcepc.voicepc.demos.web.aliyunllm.ParamsSchema;
import qiniu.voidcepc.voicepc.demos.web.exception.BusinessException;
import qiniu.voidcepc.voicepc.demos.web.server.VoiceServer;
import qiniu.voidcepc.voicepc.demos.web.utils.VoicePOJO;
import qiniu.voidcepc.voicepc.demos.web.vo.musicvo.KuWoMusicPlayer;
import qiniu.voidcepc.voicepc.demos.web.vo.musicvo.SingVo;

import java.util.List;

/**
 * NlsClient：语音处理客户端，利用该客户端可以进行一句话识别、实时语音识别和语音合成的语音处理任务。该客户端为线程安全，建议全局仅创建一个实例。
 *
 * SpeechRecognizer：一句话识别处理类，通过该接口设置请求参数，发送请求及声音数据。非线程安全。
 *
 * SpeechRecognizerListener：识别结果监听类，监听识别结果。非线程安全。
 * */
@Service
public class VoiceServerImpl implements VoiceServer {

    @Autowired
    VoicePOJO voicePOJO;

    @Autowired
    Generation gen;

    @Autowired
    private List<Message> messages;//llm对话上下文

    @Autowired
    private GetGenerationParam getGenerationParam;//模型对话参数生成类

    @Autowired
    private KuWoMusicPlayer kuWoMusicPlayer;

    @Override
    public String localVoice() {
        //String filepath= "D:\\QiNiu2\\VoicePC\\src\\main\\resources\\localVoice\\ezyZip.wav";
        String filepath= "D:\\QiNiu2\\VoicePC\\src\\main\\resources\\localVoice\\nls-sample-16k.wav";
        String sampleRate = "16000"; // 设置正确的采样率值
        voicePOJO.process(filepath, Integer.parseInt(sampleRate));
        return voicePOJO.getRecognizerresult();
    }

    @Override
    public String origianlVoid(MultipartFile file, int sampleRate) {
        try {
            // 检查文件是否为空
            if (file == null || file.isEmpty()) {
                return "上传的文件为空";
            }
            
            // 调用VoicePOJO处理上传的音频文件
            voicePOJO.process(file, sampleRate);
            return voicePOJO.getRecognizerresult();
        } catch (Exception e) {
            // 捕获异常并返回错误信息
            return "处理失败: " + e.getMessage();
        }
    }

    @Override
    public String textUseFun(String text) {
        return funcTsk(text);
    }

    /**
     * 根据语音识别调用本地的文件
     * 根据语音识别的文件字符串来判断是否需要调用本地客户端来搜索音乐
     * */
    @Override
    public String origianlVoiceTask(MultipartFile file, int sampleRate) {
        try {
            // 检查文件是否为空
            if (file == null || file.isEmpty()) {
                return "上传的文件为空";
            }

            // 调用VoicePOJO处理上传的音频文件
            voicePOJO.process(file, sampleRate);
            String task = voicePOJO.getRecognizerresult();
            return funcTsk(task);
        } catch (Exception e) {
            // 捕获异常并返回错误信息
            return "处理失败: " + e.getMessage();
        }
    }

    @Override
    public String desription(String mydescri) {
        return funcTsk(mydescri);
    }


    private String funcTsk(String text){
        // 将单个FunctionDefinition包装成列表传入
        List<FunctionDefinition> functions = Arrays.asList(ParamsSchema.getmusicFunctionForSearchAndPlay(),ParamsSchema.getmusicFunctionForPause());
        GenerationParam param = getGenerationParam.getParam(text, functions);
        //发送 param，并将接受结果，根据结果判断是不是要进行使用
        GenerationResult result = null;
        try {
            result = gen.call(param);
            Message assistantOutput = result.getOutput().getChoices().get(0).getMessage();
            messages.add(Message.builder().role(Role.ASSISTANT.getValue()).content(assistantOutput.getContent()).build());
            // 不再向全局messages列表添加assistantOutput消息，避免消息累积
            if (assistantOutput.getToolCalls() == null || assistantOutput.getToolCalls().isEmpty()) {
                // 情况A：模型没有调用工具，而是直接给出了回答。
                System.out.println("无需本地工具，直接回复：" + assistantOutput.getContent());
                return assistantOutput.getContent();
            } else {
                // 模型决定调用工具
                System.out.println();
                ToolCallBase toolCall = assistantOutput.getToolCalls().get(0);

                // 从模型的回复中解析出工具调用的具体信息（要调用的函数名、参数）。
                ToolCallFunction functionCall = (ToolCallFunction) toolCall;
                String funcName = functionCall.getFunction().getName();
                String arguments = functionCall.getFunction().getArguments();
                System.out.println("正在调用工具 [" + funcName + "]，参数：" + arguments);

                if(funcName.equals("searchAndPlay")) {
                    // 创建 ObjectMapper 实例
                    ObjectMapper objectMapper = new ObjectMapper();

                    // 将 JSON 字符串解析为 SingVo 对象
                    SingVo singVo = objectMapper.readValue(arguments, SingVo.class);
                    kuWoMusicPlayer.searchAndPlay(singVo.getSongName(),singVo.getArtistName());
                } else if(funcName.equals("pause")) {
                    kuWoMusicPlayer.stopOrdisplaySing();
                }
            }
            return assistantOutput.getContent();
        } catch (NoApiKeyException e) {
            throw new BusinessException("API密钥错误", "401", e);
        } catch (InputRequiredException e) {
            throw new BusinessException("输入参数缺失", "400", e);
        } catch (JsonMappingException e) {
            throw new BusinessException("JSON数据映射失败", "400", e);
        } catch (JsonProcessingException e) {
            throw new BusinessException("JSON解析错误", "400", e);
        } catch (Exception e) {
            throw new BusinessException("处理文本指令时发生错误", "500", e);
        }
    }
}
